package com.t.bricks.bussiness.service.ignoreurl.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.springframework.stereotype.Service;

import com.t.bricks.bussiness.db.entity.ignoreurl.IgnoreURL;
import com.t.bricks.bussiness.db.entity.ignoreurl.SimpleIgonoreURL;
import com.t.bricks.bussiness.service.ignoreurl.IgnoreURLService;
import com.t.bricks.model.MsgEmity;
import com.t.bricks.utils.function.data.CacheTxtUtil;
import com.t.bricks.utils.function.data.IntegerUtil;

/**
 * 拦截器忽略路径'IgnoreURL表'基本业务操作类接口实现
 */
@Service
public class IgnoreURLServiceImpl implements IgnoreURLService<IgnoreURL> {
	
	/**
	 * 路径缓存(全部)免登录
	 */
	private static Map<String, String> cacheSetNotLogin = null;
	
	/**
	 * 路径缓存(仅包含/*的路径)免登录
	 */
	private static Map<String, String> cacheSubSetNotLogin = null;
	
	/**
	 * 路径缓存(全部)必须登录
	 */
	private static Map<String, String> cacheSetLogin = null;
	
	/**
	 * 路径缓存(仅包含/*的路径)必须登录
	 */
	private static Map<String, String> cacheSubSetLogin = null;

	/**
	 * 启动时检查建立缓存
	 */
	@PostConstruct
	private void autoRun() {
		initCacheMap();//初始化缓存
	}

	/**
	 * 获取不拦截路径集合
	 * @param sMustLogins 待获取系统编号
	 * @return
	 */
	@Override
	public Map<String, Integer> findIgnoreUrlList(String sMustLogins) {
		List<Integer> iMustLogins = IntegerUtil.strToList(sMustLogins, ";");
		
		MsgEmity me = this.callMapping("findIgnoreURLList", iMustLogins);
		if (!me.isSuccess()) {
			return null;
		}
		
		List<SimpleIgonoreURL> list = me.getData();
		Map<String, Integer> map = new HashMap<String, Integer>();
		for (SimpleIgonoreURL simpleIgonoreURL : list) {
			String ignoreUrl = simpleIgonoreURL.getsIgnoreUrl();
			if (null == ignoreUrl || "".equals(ignoreUrl.trim())) {
				continue;
			}
			
			String [] array = ignoreUrl.split(";");
			for (String string : array) {
				string = string.trim();
				if (!"".equals(string)) {
					map.put(string, simpleIgonoreURL.getiMustLogin());
				}
			}
		}
		
		return map;
	}
	
	/**
	 * 验证指定url是否在可忽略的访问路径中(给内部拦截器用,直接返回Boolean)
	 * @param sUrl 待检验的url
	 * @param isMustLogin 是否必须登录
	 * @param sUserType 待检验的用户类型
	 * @return
	 */
	@Override
	public boolean checkIgnoreUrl(String sUrl, Integer iMustLogin, String sUserType) {
		if (null == sUrl || "".equals(sUrl.trim())) {
			return false;// MsgEmity.err(8001, "请求检验的Url参数为空");
		}
		
		initCacheMap();//初始化缓存
		
		sUrl = sUrl.trim();

		iMustLogin = (null == iMustLogin || iMustLogin.intValue() != 1) ? 2 : 1;//1为必须登录
		
		//--在免登录的明确路径中找--//
		for (Map.Entry<String, String> entry: cacheSetNotLogin.entrySet()) {
			if (sUrl.equals(entry.getKey())) {
				return true;//在免登录的免拦截中发现
			}
		}
		
		//--在免登录的明确路径中中没找到,则可能属于子路径请求--//
		for (Map.Entry<String, String> entry: cacheSubSetNotLogin.entrySet()) {
			if (sUrl.contains(entry.getKey())) {
				return true;//在免登录的免拦截中发现
			}
		}

		if (1 != iMustLogin.intValue()) {//未指定要"必须登录"
			return false;// MsgEmity.err(8003, "在指定项目中都没有找到可以免拦截的约定");//不符合
		}
		
		//--指定要"必须登录"--//
		
		if (null != sUserType && !"".equals(sUserType.trim())) {
			sUserType = String.format(";%s;", sUserType.trim());
		} else {
			sUserType = null;
		}
		
		for (Map.Entry<String, String> entry: cacheSetLogin.entrySet()) {
			if (!sUrl.equals(entry.getKey())) {
				continue;
			}
			
			if (entry.getValue() == null || "".equals(entry.getValue())) {
				return true;//在必须登录的免拦截(明确路径)中发现,并且不限定用户
			}
			
			if (null != sUserType && !entry.getValue().contains(sUserType)) {
				continue;//拦截路径的使用限定了用户类型
			}
			
			return true;//在必须登录的免拦截(明确路径)中发现
		}

		for (Map.Entry<String, String> entry: cacheSubSetLogin.entrySet()) {
			if (!sUrl.contains(entry.getKey())) {
				continue;
			}
			
			if (entry.getValue() == null) {
				return true;//在必须登录的免拦截(子路径)中发现,并且不限定用户
			}
			
			if (null != sUserType && !entry.getValue().contains(sUserType)) {
				continue;//拦截路径的使用限定了用户类型
			}
			
			return true;//在必须登录的免拦截(子路径)中发现
		}

		return false;// MsgEmity.err(8003, "在指定项目中都没有找到可以免拦截的约定");//不符合
	}
	
	/**
	 * 初始化缓存
	 * @return
	 */
	private void initCacheMap() {
		if (null != cacheSetNotLogin) {
			return;
		}
		
		synchronized(this) {
			if (null != cacheSetNotLogin) {
				return;
			}

			String filePath = String.format("%s/temp/cache/IgnoreURL/IgnoreURL.txt",
					System.getProperty("user.dir").replaceAll("\\\\", "/"));
			List<Map<String, String>> caches = CacheTxtUtil.readCacheFile(Map.class, filePath);//读取预存储的缓存文件
			if (null != caches && caches.size() == 4) {
				cacheSetNotLogin = caches.get(0);
				cacheSubSetNotLogin = caches.get(1);
				cacheSetLogin = caches.get(2);
				cacheSubSetLogin = caches.get(3);
				
				return;
			}

			MsgEmity me = this.callMapping("allIgnoreUrlList");
			if (!me.isSuccess()) {
				return;
			}

			cacheSetNotLogin = new HashMap<String, String>();
			cacheSubSetNotLogin = new HashMap<String, String>();
			cacheSetLogin = new HashMap<String, String>();
			cacheSubSetLogin = new HashMap<String, String>();
			
			List<SimpleIgonoreURL> list = me.getData();
			for (SimpleIgonoreURL simpleIgonoreURL : list) {
				String sIgnoreUrl = simpleIgonoreURL.getsIgnoreUrl();
				if (null == sIgnoreUrl || "".equals(sIgnoreUrl.trim())) {
					continue;
				}
				
				String [] array = sIgnoreUrl.split(";");
				for (String string : array) {
					string = string.trim();
					if ("".equals(string)) {
						continue;
					}
					
					if (simpleIgonoreURL.getiMustLogin() != 1) {
						cacheSetNotLogin.put(string, "");
					} else if (null == simpleIgonoreURL.getsOnlyUserType() || "".equals(simpleIgonoreURL.getsOnlyUserType())) {
						cacheSetLogin.put(string, "");
					} else {
						cacheSetLogin.put(string, ";" + simpleIgonoreURL.getsOnlyUserType() + ";");
					}

					if (!string.contains("/*")) {//如果不包含*,说明没有下级
						continue;
					}
					
					string = string.replace("/*", "");
					if (simpleIgonoreURL.getiMustLogin() != 1) {//如果包含*,说明要忽略其下级
						cacheSubSetNotLogin.put(string, "");
					} else if (null == simpleIgonoreURL.getsOnlyUserType() || "".equals(simpleIgonoreURL.getsOnlyUserType())) {
						cacheSubSetLogin.put(string, "");
					} else {
						cacheSubSetLogin.put(string, ";" + simpleIgonoreURL.getsOnlyUserType() + ";");
					}
				}
			}
			
			caches = new ArrayList<Map<String, String>>(4);
			caches.add(cacheSetNotLogin);
			caches.add(cacheSubSetNotLogin);
			caches.add(cacheSetLogin);
			caches.add(cacheSubSetLogin);
			
			CacheTxtUtil.createCacheFile(caches, filePath);//写入文件，以便用户权限验证模块使用
		}
	}
	
	/**
	 * 清理缓存
	 * @return
	 */
	@Override
	public MsgEmity clearCache() {
		cacheSetNotLogin = null;
		cacheSubSetNotLogin = null;
		cacheSetLogin = null;
		cacheSubSetLogin = null;

		CacheTxtUtil.delCacheFile(String.format("%s/temp/cache/IgnoreURL/IgnoreURL.txt",
				System.getProperty("user.dir").replaceAll("\\\\", "/")));
		
		initCacheMap();//初始化缓存,有必要进行,否则会导致拦截器进入访问时第一个会慢
		
		return MsgEmity.success(8999, "请求清理缓存成功！");
	}
	
}
